/**
 * Class: OpenLayers.Layer.PoiLayer
 * POI图层，用于显示POI图层
 *
 * 继承自:
 *  - <OpenLayers.Layer>
 * @requires OpenLayers/Layer/Markers.js
 */
OpenLayers.Layer.DynaPoiLayer = OpenLayers.Class(OpenLayers.Layer.Markers, {
    /**
     * 根据poi的类型分类的marker集合
     * @type {JSON}
     * @property typemarkers
     */
    typemarkers: null,
    /**
     * 根据id缓存marker是否存在
     * @type {JSON}
     * @property idmarkers
     */
    idmarkers: null,
    /**
     * 鼠标滑过显示POI标注
     * @type {Boolean}
     * @property overshow
     */
    overshow: false,
    /**
     * POI数据
     * {
     * "type": [
     * {"id":id1, "x": x1, "y": y1, title: "<p>xxxxx</p>"},
     * {"id":id2, "x": x2, "y": y2, title: "<p>xxxxx</p>"},
     * {"id":id3, "x": x3, "y": y3, title: "<p>xxxxx</p>"},
     * {"id":id4, "x": x4, "y": y4, title: "<p>xxxxx</p>"}
     * ]
     * }
     * @type {JSON}
     * @property data
     */
    data: null,
    /**
     * poi标注信息图层
     * @type {Object}
     * @property labelLayer
     */
    labelLayer: null,
    /**
     * 最后选中的marker
     */
    lastSelectedMarker: null,
    /**
     * 上次高亮的poi
     */
    lastHighlightMarker: null,
    /**
     * 点击POI的回调函数
     * @type {Function}
     * @property clickEnd
     */
    clickEnd: null,
    
    /**
     * 初始化
     * @constructor
     * @param {String} name 图层名称
     * @param {Object} options 参数
     */
    initialize: function(name, options){
        OpenLayers.Layer.Markers.prototype.initialize.apply(this, arguments);
    },
    
    /**
     * 指定PoiLayer所归属的地图对象，当图层加至地图时触发此方法
     * @method setMap
     * @param {Object} map 地图对象
     */
    setMap: function(map) {
        OpenLayers.Layer.prototype.setMap.apply(this, arguments); 
        
        //添加标注图层
        this.labelLayer = new OpenLayers.Layer.Labels("poi_labelLayer");
        this.map.addLayer(this.labelLayer);
        var poiindex = map.Z_INDEX_BASE["Popup"];
        this.setZIndex(poiindex);
        this.labelLayer.setZIndex(poiindex+1);
        
        this.div.style.cursor = "pointer";
        this.createPois(this.map.getMaxExtent());
    },
    
    /**
     * 创建所有的POI
     * @method createPois
     * @param {Object} bounds 地图四至
     */
    createPois: function(bounds){
        this.initCacheData();
		//获取poi数据
		if(this.data){
			this.createMarkers();
		}
    },
    
    /**
     * 
     */
    refreshMarkers: function(){},
    
    /**
     * 清除markers
     * @method clearPoiMarkers
     */
    clearPoiMarkers: function(){
        this.clearMarkers();
        this.typemarkers = null;
        this.idmarkers = null;
        this.initCacheData();
    },
    
    /**
     * 初始化缓存数据
     * @method initCacheData
     */
    initCacheData: function(){
        //缓存数据
		this.idmarkers = {};
		this.typemarkers = {};
    },
    
    /**
     * 创建icon对象
     * @method createIcon
     * @param {Object} poidata POI数据
     * @param {Function} cback 回调函数
     */
    createIcon: function(poidata, cback){
        var align = poidata.align || "center_bottom";
        var img = new Image();
        var scope = this;
        img.onload = function(){
            var size = new OpenLayers.Size(img.width, img.height);
            var offsets = scope.getOffset(img.width, img.height, align);
            var icon = new OpenLayers.Icon(poidata.icon,size,offsets[0]);
            icon.labelOffset = offsets[1];
            if(cback){
                cback.apply(scope, [icon]);
            }
        }
        img.src = poidata.icon;
    },
    
    /**
     * 图标偏移
     * @method getOffset
     * @param {Float} w 图标width
     * @param {Float} h 图标height
     * @param {String} align 图标箭头位置
     */
    getOffset: function(w, h, align){
        var offsetx = 0,offsety = 0;
        var labelx = 0,labely = 0;
        switch(align){
            case "top_left":{
                labelx = w;
                break;
            }
            case "top_center":{
                offsetx = -w/2;
                labelx = w/2;
                break;
            }
            case "top_right":{
                offsetx = -w;
                break;
            }
            case "center_left":{
                offsety = -h/2;
                labelx = w;
                labely = -h/2;
                break;
            }
            case "center_center":{
                offsetx = -w/2;
                offsety = -h/2;
                labelx = w/2;
                labely = -h/2;
                break;
            }
            case "center_right":{
                offsetx = -w;
                offsety = -h/2;
                labely = -h/2;
                break;
            }
            case "bottom_left":{
                offsety = -h;
                labelx = w;
                labely = -h;
                break;
            }
            case "bottom_center":{
                offsetx = -w/2;
                offsety = -h;
                labelx = w/2;
                labely = -h;
                break;
            }
            case "bottom_right":{
                offsetx = -w;
                offsety = -h;
                labely = -h;
                break;
            }
        }
        return [new OpenLayers.Pixel(offsetx, offsety), new OpenLayers.Pixel(labelx, labely)];
    },
    
    /**
     * 根据poi数据创建所有marker
     * @method createMarkers
     */
    createMarkers: function() {
        for(var i in this.data){
            var typedata = this.data[i];
            this.createsingleTypeMarkers(typedata, i);
        }
    },
    
    /**
     * 根据poi数据创建所有单个marker
     * @method createsingleTypeMarkers
     * @param {Object} typedata 某一类型的POI数据
     * @param {String} typeName POI类型
     */
    createsingleTypeMarkers: function(typedata, typeName) {
        if(!this.typemarkers[typeName]){
            this.typemarkers[typeName]=[];
        }
		
        //为了提高绘制marker的效率将减少marker注册事件的BROWSER_EVENTS中的事件名称。
        //在创建完了所有的marker之后还原BROWSER_EVENTS。
        var browser_events = OpenLayers.Events.prototype.BROWSER_EVENTS;
        OpenLayers.Events.prototype.BROWSER_EVENTS = ["mouseout","mousemove","click"];
        
        var data = typedata.data;
        var scope = this;
        
        for(var j in data){
            var x = data[j].x || data[j].X;
            var y = data[j].y || data[j].Y;
            var lonlat = new OpenLayers.LonLat(x,y);
            
            this.createMarker(typeName, lonlat, data[j], function(marker){
                scope.appendMarker(marker);
                scope.typemarkers[typeName].push(marker);
                scope.idmarkers[marker.id] = marker;
            });
        }
        
        //还原OpenLayers.Events.prototype.BROWSER_EVENTS
        OpenLayers.Events.prototype.BROWSER_EVENTS = browser_events;
   },
    
    
    /**
     * 添加marker对象
     * @method appendMarker
     * @param {Object} marker marker对象
     */
    appendMarker: function(marker){
        this.addMarker(marker);
    },
    
    /**
     * 创建marker对象
     * @method createMarker
     * @param {String} typename 类型
     * @param {LonLat} lonlat 坐标
     * @param {Object} poidata 该POI的数据
     * @param {Function} cback 回调函数
     */
    createMarker: function(typename, lonlat, poidata, cback) {
        var scope = this;
        this.createIcon(poidata, function(icon){
            var marker = new OpenLayers.Marker(lonlat,icon.clone());
            marker.data = poidata;
            marker.defaultIcon = icon.url;
            marker.activeIcon = poidata.activeIcon;
            marker.typeName = typename;
            marker.id = poidata.id || poidata.ID;
            var options = {
                poidata : poidata,
                lonlat  : lonlat,
                owner   : scope,
                marker  : marker,
                icon    : icon
            };
            //注册鼠标点击事件
            marker.events.register('click', options, scope.onMouseClick);
            
            if(!this.overshow){
                //添加标注
                var title = poidata.title || poidata.TITLE;
                var label = new OpenLayers.Label(lonlat, title, "dynaPoiLabel");
                label.alwaysleft = true;
                label.offset = icon.labelOffset;
                marker.label = label;
                this.labelLayer.add(label);
            }else{
                //注册鼠标滑过事件
                marker.events.register('mouseover', options, this.onMouseMove);
                marker.events.register('mouseout', options, this.onMouseOut);
            }
            
            cback(marker);
        });
    },
    
    /**
     * 响应鼠标点击事件
     * @method onMouseClick
     * @param {Object} evt 事件对象
     */
    onMouseClick: function(evt){
        var poidata = this.poidata;
        var owner = this.owner;
        //高亮POI
		if(!owner.isMarkerEqual(this.marker, owner.lastSelectedMarker)){
			//清除上次点击的poi的高亮状态
			if(owner.lastSelectedMarker != null){
				owner.clearHighlight(owner.lastSelectedMarker);
			}
		    owner.lastSelectedMarker = this.marker;
		    owner.highlightPOI(this.marker);
		}
        
        
        //clickEnd外部自定义点击响应
        if(owner.clickEnd !== null && typeof owner.clickEnd == "function"){
            owner.clickEnd(this);
        }
    },
    
    /**
     * 响应鼠标滑过事件
     * @method onMouseMove
     * @param {Object} evt 事件对象
     */
    onMouseMove: function(evt){
        //清除掉标注信息
        var owner = this.owner;
        owner.labelLayer.clear();
        var poidata = this.poidata;
        
        //添加标注
        var title = poidata.title || poidata.TITLE;
        var label = new OpenLayers.Label(this.marker.lonlat, title, "dynaPoiLabel");
        label.alwaysleft = true;
        label.offset = this.icon.labelOffset;
        owner.labelLayer.add(label);
    },
    
    /**
     * 响应鼠标滑出事件
     * @method onMouseMove
     * @param {Object} evt 事件对象
     */
    onMouseOut: function(evt) {
        //清除掉标注信息
        var owner = this.owner;
        owner.labelLayer.clear();
    },
    
    /**
     * 高亮POI
     * 如果当前poi的poiTypeParam中的activateImgURL属性有值则高亮该poi
	 * 先清除上次选中的poi的高亮状态
     */
    highlightPOI: function(currentMarker) {
    	var activeImgUrl = currentMarker.activeIcon;
    	//如果存在高亮图标
    	if(activeImgUrl != null){
	    	if(this.lastHighlightMarker != null && !this.isMarkerEqual(this.lastHighlightMarker, this.lastSelectedMarker)){
	    		this.clearHighlight(this.lastHighlightMarker);
	    	}
	    	currentMarker.setUrl(activeImgUrl);
	    	this.lastHighlightMarker = currentMarker;
	    }
    },
    
    /**
     * 消除高亮
     */
    clearHighlight: function(marker) {
    	if(marker != null){
    		var iconImgURL = marker.defaultIcon;
    		marker.setUrl(iconImgURL);
    	}
    },
    
    /**
     * 判断两个poi是否相同
     * @method isMarkerEqual
     * @param {Object} marker1 marker对象
     * @param {Object} marker2 marker对象
     */
    isMarkerEqual: function(marker1, marker2) {
        if(marker1 === null){
            return false;
        }
        if(marker2 === null){
            return false;
        }
        var poitype1 = marker1.typeName;
        var poitype2 = marker2.typeName;
        var id1 = marker1.data.id || marker1.data.ID;
        var id2 = marker2.data.id || marker2.data.ID;
        
        //当poi的类型相同，并且poi的id相同则视为两个poi相同。
        if((poitype1 == poitype2) && (id1 == id2)){
            return true;
        }else{
            return false;
        }
    },
    
    /**
     * 显示或隐藏markers
     * @method dispalyMarkers
     * @param {Array} markers marker数组
     * @param {Boolean} display 显示与否
     */
    dispalyMarkers: function(markers, display) {
        for(var i in markers){
            if(markers[i].id) {
                markers[i].icon.display(display);
            }
        }
    },
    
    /**
     * 设置关联图层
     * @method connectLayer
     * @param {Object} layer 
     */
    connectLayer: function(layer) {
        layer.events.register("visibilitychanged", {connectLayer:layer,poiLayer:this}, this.visibilityChange);
    },
   
   /**
    * 关联图层可见变化后清除poi
    * @method visibilityChange
    */
    visibilityChange: function() {
        this.poiLayer.setVisibility(this.connectLayer.visibility);
        this.poiLayer.clearPoiMarkers();
        this.labelLayer.setVisibility(this.connectLayer.visibility);
        this.labelLayer.clear();
    },
    
    /**
     * 删除图层时触发
     * @method removeMap
     * @param {Object} objmap 
     */
    removeMap: function(objmap) {
        if(this.labelLayer && this.labelLayer.div){
            this.map.removeLayer(this.labelLayer);
            this.labelLayer.destroy();
        }
    },
   
    /**
     * 类名
     * @type {String}
     * @property CLASS_NAME
     */
    CLASS_NAME: "OpenLayers.Layer.DynaPoiLayer"
});



